﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace M.Win
{
	/// <summary>
	/// 用于WinForm开发的友情工具库
	/// </summary>
	public static class Util
	{
		#region DLL Import
		/// <summary>
		/// 是否为64位进程
		/// </summary>
		/// <param name="hProcess"></param>
		/// <param name="wow64Process"></param>
		/// <returns></returns>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1060:MovePInvokesToNativeMethodsClass"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Interoperability", "CA1400:PInvokeEntryPointsShouldExist"), DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)]
		[return: MarshalAs(UnmanagedType.Bool)]
		private static extern bool IsWow64Process(
		[In] IntPtr hProcess,
		[Out] out bool wow64Process
		);
		/// <summary>
		/// 设置前置窗口
		/// </summary>
		/// <param name="hwnd"></param>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1060:MovePInvokesToNativeMethodsClass"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Interoperability", "CA1401:PInvokesShouldNotBeVisible"), DllImport("User32.dll")]
		public static extern void SetForegroundWindow(IntPtr hwnd);
		/// <summary>
		/// 同步显示窗体
		/// </summary>
		/// <param name="hWnd"></param>
		/// <param name="cmdShow"></param>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1060:MovePInvokesToNativeMethodsClass"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Interoperability", "CA1401:PInvokesShouldNotBeVisible"), DllImport("User32.dll")]
		public static extern void ShowWindowAsync(IntPtr hWnd, int cmdShow);
		/// <summary>
		/// 向窗体句柄发送消息
		/// </summary>
		/// <param name="hWnd"></param>
		/// <param name="Msg"></param>
		/// <param name="wParam"></param>
		/// <param name="lParam"></param>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1060:MovePInvokesToNativeMethodsClass"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Interoperability", "CA1401:PInvokesShouldNotBeVisible"), DllImport("User32.dll", EntryPoint = "SendMessage")]
		public static extern void SendMessage(IntPtr hWnd, int Msg, int wParam, ref CopyDataStruct lParam);
		/// <summary>
		/// 查找窗体句柄
		/// </summary>
		/// <param name="classname"></param>
		/// <param name="text"></param>
		/// <returns></returns>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1060:MovePInvokesToNativeMethodsClass"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Portability", "CA1901:PInvokeDeclarationsShouldBePortable", MessageId = "return"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA2101:SpecifyMarshalingForPInvokeStringArguments", MessageId = "0"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA2101:SpecifyMarshalingForPInvokeStringArguments", MessageId = "1"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Interoperability", "CA1401:PInvokesShouldNotBeVisible"), DllImport("user32.dll")]
		public static extern Int32 FindWindow(String classname, String text);
		/// <summary>
		/// 获取DC
		/// </summary>
		/// <param name="hWnd"></param>
		/// <returns></returns>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1060:MovePInvokesToNativeMethodsClass"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Interoperability", "CA1401:PInvokesShouldNotBeVisible"), System.Runtime.InteropServices.DllImport("user32.dll")]
		public static extern IntPtr GetWindowDC(IntPtr hWnd);
		/// <summary>
		/// 释放DC
		/// </summary>
		/// <param name="hWnd"></param>
		/// <param name="hDC"></param>
		/// <returns></returns>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1060:MovePInvokesToNativeMethodsClass"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Interoperability", "CA1401:PInvokesShouldNotBeVisible"), System.Runtime.InteropServices.DllImport("user32.dll")]
		public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
		#endregion

		#region Windows Message 定义
		/// <summary>
		/// 进程间通讯用到的Windows Message
		/// </summary>
		public const int WM_COPYDATA = 0x004A;
		/// <summary>
		/// 系统关机向应用程序发送的Windows Message
		/// </summary>
		public const int WM_QUERYENDSESSION = 0x0011;
		#endregion

		#region 进程间通信消息结构
		/// <summary>
		/// 进程间通信消息结构
		/// </summary>
		public struct CopyDataStruct
		{
			/// <summary>
			/// 消息数据
			/// </summary>
			[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")]
			public IntPtr dwData;
			/// <summary>
			/// 通讯数据长度
			/// </summary>
			public int cbData;
			/// <summary>
			/// 通讯数据
			/// </summary>
			[MarshalAs(UnmanagedType.LPStr)]
			public string lpData;
		}
		#endregion

		#region 检查当前进程是否为64位
		/// <summary>
		/// 检查当前进程是否为64位
		/// </summary>
		/// <returns>当前进程是否为64位</returns>
		public static bool Is64BitOperationSystem()
		{
			bool is64BitProcess = (IntPtr.Size == 8);
			bool is64BitOperatingSystem = is64BitProcess || internalCheckIsWow64();
			return is64BitOperatingSystem;
		}
		private static bool internalCheckIsWow64()
		{
			if ((Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor >= 1) ||
			Environment.OSVersion.Version.Major >= 6)
			{
				using (Process p = Process.GetCurrentProcess())
				{
					bool retVal;
					if (!IsWow64Process(p.Handle, out retVal))
					{
						return false;
					}
					return retVal;
				}
			}
			else
			{
				return false;
			}
		}
		#endregion

		#region 获取指定点所在的屏幕
		/// <summary>
		/// 获取指定点所在的屏幕，用于多显示器正确识别
		/// </summary>
		/// <param name="point">指定点</param>
		/// <returns>指定点所在屏幕</returns>
		public static System.Windows.Forms.Screen GetScreen(System.Drawing.Point point)
		{
			foreach (System.Windows.Forms.Screen s in System.Windows.Forms.Screen.AllScreens)
			{
				if (point.X >= s.Bounds.X && point.X < (s.Bounds.X + s.Bounds.Width))
					return s;
			}
			return System.Windows.Forms.Screen.PrimaryScreen;
		}
		#endregion

		#region 获取屏幕截图
		/// <summary>
		/// 获取屏幕截图
		/// </summary>
		/// <param name="rectangle">需要截取的位置及大小</param>
		/// <returns>屏幕截图</returns>
		public static System.Drawing.Bitmap GetScreenCapture(System.Drawing.Rectangle rectangle)
		{
			System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(rectangle.Width, rectangle.Height);
			System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bmp);
			g.CopyFromScreen(rectangle.Location,
				new System.Drawing.Point(0, 0),
				rectangle.Size);
			g.Save();
			return bmp;
		}
		#endregion

		#region 进程间通讯相关
		/// <summary>
		/// 创建进程通讯的共享消息
		/// </summary>
		/// <param name="message">需要共享的消息</param>
		/// <returns></returns>
		public static CopyDataStruct CreateProcessCallData(string message)
		{
			return CreateProcessCallData(message, Encoding.Default);
		}
		/// <summary>
		/// 创建进程通讯的共享消息
		/// </summary>
		/// <param name="message">需要共享的消息</param>
		/// <param name="encoding">消息编码</param>
		/// <returns></returns>
		public static CopyDataStruct CreateProcessCallData(string message, Encoding encoding)
		{
			MValidator.CheckForEmptyString("Process Call Message", message);
			if (encoding == null) encoding = System.Text.Encoding.Default;
			CopyDataStruct CDS = new CopyDataStruct();
			CDS.dwData = (IntPtr)100;
			CDS.lpData = message;
			CDS.cbData = encoding.GetBytes(message).Length + 1;
			return CDS;
		}

		#endregion

		#region 获取目录
		/// <summary>
		/// 获取当前应用程序集文件路径
		/// </summary>
		/// <remarks>通过进程查找</remarks>
		/// <returns>包含进程MainModule的文件路径，包含.exe</returns>
		public static string GetCurrentFilePath()
		{
			return Process.GetCurrentProcess().MainModule.FileName;
		}

		/// <summary>
		/// 获取当前应用程序集文件所在目录
		/// </summary>
		/// <remarks>通过进程查找</remarks>
		/// <returns></returns>
		public static string GetCurrentDirectory()
		{
			string filePath = Util.GetCurrentFilePath();
			return filePath.Substring(0, filePath.LastIndexOf("\\") + 1);
		}
		#endregion
	}
}
